/*
 * Created by Jaren at 2021/8/21 14:50
 */
import 'dart:typed_data';

import 'package:binary/binary.dart';
import 'package:inmotion_protocol/base/base_message.dart';
import 'package:inmotion_protocol/ezcan/ezcan_constant.dart';
import 'package:inmotion_protocol/util/byte_util.dart';

class EzcanMessage extends IMessage {

    static const int sMinLength = 2 + 4 + 8 + 1 + 1 + 1 + 1 + 1 + 2;

    Uint8ClampedList head = Uint8ClampedList.fromList([EzcanConstant.HEAD1, EzcanConstant.HEAD2]); // 消息头
    Uint32 id; // id, 4byte
    Uint8ClampedList data; // data，用来指示data长度的length在data之后，所以在一包数据中无法通过length确定data的长度。之前可能是收发双方约定了data长度固定为8
    Uint8 length; // data段长度，≤8，当length为0xFE时，代表该消息带扩展数据，其中data[0]-data[3]表示扩展数据长度
    Uint8 channel; // app主动请求的消息，channel固定为0x05
    Uint8 format; // 消息格式，0标准格式，1扩展格式
    Uint8 type; // 读写类型，写1，读0
    Uint8ClampedList? extra; // 扩展数据
    Uint8? check; // 校验位，和校验
    Uint8ClampedList tail = Uint8ClampedList.fromList([EzcanConstant.TAIL1, EzcanConstant.TAIL2]); // 消息尾

    EzcanMessage(this.id, this.data, this.length, this.channel, this.format, this.type, this.extra, this.check) {
        check ??= ByteUtil.toUint8(genCheck(
            id,
            data,
            length,
            channel,
            format,
            type,
            extra));
    }

    @override
    String genMsgIdentity() {
        return (id.value & 0x00FFFFFF).toString();
    }

    @override
    String toString() {
        return "EzcanMessage{"
            "id: 0x" + ByteUtil.bytes2HexStringLe(ByteUtil.num2BytesLe(id.value, 4)) +
            ", data: " + ByteUtil.bytes2HexString(data) +
            ", length: " + ByteUtil.byte2Hex(ByteUtil.byte2UInt(length.value)) +
            ", channel: " + ByteUtil.byte2Hex(channel.value) +
            ", format:  " + ByteUtil.byte2Hex(format.value) +
            ", type:  " + ByteUtil.byte2Hex(type.value) +
            ", extra: " + (extra == null ? 'null' : ByteUtil.bytes2HexString(extra!)) +
            ", check: " + ByteUtil.byte2Hex(check!.value) +
            "}";
    }

    static int genCheck(Uint32 id, Uint8ClampedList? data, Uint8 length, Uint8 channel, Uint8 format, Uint8 type, Uint8ClampedList? extra) {
        int sum = 0;
        Uint8ClampedList idBytes = ByteUtil.num2BytesLe(id.value, 4);
        for (int b in idBytes) {
            sum += b;
        }
        if (data != null && data.isNotEmpty) {
            for (int b in data) {
                sum += b;
            }
        }
        sum += length.value;
        sum += channel.value;
        sum += format.value;
        sum += type.value;
        if (ByteUtil.byteEquals(format.value, EzcanConstant.FORMAT_EXTRA)) {
            for (int b in extra!) {
                sum += b;
            }
        }
        return ByteUtil
            .toInt8(sum)
            .value;
    }
}